iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 10
1

引言

Day9連結:https://ithelp.ithome.com.tw/articles/10219455
昨天我們簡單得討論了關於旋轉矩陣的概念,還沒看過的朋友可以點上面的連結去看看哦!

今天我們一樣要使用C語言來實作座標軸旋轉的模擬:利用旋轉矩陣
有了這個基礎,你就可以GET「旋轉」技能,看到電視囉XD(昨天的梗


座標公式Review

我們先來再次Review昨天得出的旋轉後座標公式:
( 假設旋轉前座標是(x, y, z),以下公式將原本為0的項簡化 )

  1. 繞著X軸旋轉(低頭、仰頭)
    https://chart.googleapis.com/chart?cht=tx&chl=%5Cleft%20(%201%20%5Ctimes%20%20x%2C%20cos%5Ctheta%20_%7Bx%7D%20%5Ctimes%20y%20%2B%20%5Cleft%20(%20-sin%5Ctheta%20_%7Bx%7D%20%5Cright%20)%20%5Ctimes%20z%2C%20sin%5Ctheta%20_%7Bx%7D%20%5Ctimes%20%20y%20%2B%20cos%5Ctheta%20_%7Bx%7D%20%5Ctimes%20%20z%5Cright%20)
    用程式邏輯來想的話,就是將逗點分開的三項分別賦值給新的x, y, z:
    https://chart.googleapis.com/chart?cht=tx&chl=newX%20%5Cleftarrow%20%201%20%5Ctimes%20%20x
    https://chart.googleapis.com/chart?cht=tx&chl=newY%20%5Cleftarrow%20%20cos%5Ctheta%20_%7Bx%7D%20%5Ctimes%20y%20%2B%20%5Cleft%20(%20-sin%5Ctheta%20_%7Bx%7D%20%5Ctimes%20z%20%5Cright%20)
    https://chart.googleapis.com/chart?cht=tx&chl=newZ%20%5Cleftarrow%20%20sin%5Ctheta%20_%7Bx%7D%20%5Ctimes%20y%20%2B%20cos%5Ctheta%20_%7Bx%7D%20%5Ctimes%20z
  2. 繞著Y軸旋轉(向左轉頭、向右轉頭)
    https://chart.googleapis.com/chart?cht=tx&chl=%5Cleft%20(%20cos%5Ctheta%20_%7By%7D%20%5Ctimes%20x%20%2B%20sin%5Ctheta%20_%7By%7D%20%5Ctimes%20%20z%2C%201%20%5Ctimes%20%20y%2C%20%5Cleft%20(%20-sin%5Ctheta%20_%7By%7D%20%5Cright%20)%20%20%20%5Ctimes%20x%20%2B%20cos%5Ctheta%20_%7By%7D%20%5Ctimes%20%20z%5Cright%20)
    同上:
    https://chart.googleapis.com/chart?cht=tx&chl=newX%20%5Cleftarrow%20%20cos%5Ctheta%20_%7By%7D%20%5Ctimes%20x%20%2B%20sin%5Ctheta%20_%7By%7D%20%5Ctimes%20z
    https://chart.googleapis.com/chart?cht=tx&chl=newY%20%5Cleftarrow%201%20%5Ctimes%20y
    https://chart.googleapis.com/chart?cht=tx&chl=newZ%20%5Cleftarrow%20-sin%5Ctheta%20_%7By%7D%20%5Ctimes%20x%20%2B%20cos%5Ctheta%20_%7By%7D%20%5Ctimes%20z

因此我們就照著上面的公式寫出程式吧!


C語言實作

  1. 首先先列出一些變數
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    int ox, oy, oz;  // 使用者輸入原始座標
    float rx, ry, rz;  // 座標軸旋轉後座標
    double theta_x, theta_y, sin_x, sin_y, cos_x, cos_y;  // 設定旋轉角度用、存放三角函數結果用
    
  1. 向使用者取得原始座標
    printf("請輸入原始座標(ox, oy, oz):\n");
    scanf("%d %d %d", &ox, &oy, &oz);
    printf("原始: ox:%d oy:%d oz:%d\n\n", ox, oy, oz);
  1. 為了讓使用者可以不斷輸入旋轉角度實驗,加上無窮迴圈
    for(;;)
    {
        printf("請輸入旋轉角度(theta_x, theta_y)(弧度):\n");
        scanf("%lf %lf", &theta_x, &theta_y);
  1. 將會運算到的三角函數值先算好(三角函數運算較耗時)
        sin_x = sin(theta_x);  // 先行計算三角函數值
        sin_y = sin(theta_y);
        cos_x = cos(theta_x);
        cos_y = cos(theta_y);
  1. 帶入公式,先繞x軸旋轉,再繞y軸旋轉
        rx = ox;  // 先初始化,稍後全部以rx計算,ox當作保存原始值
        ry = oy;
        rz = oz;

        // 繞x軸旋轉
        rx = rx;
        int temp_y = ry;  // 稍後ry會被蓋掉,先保存起來
        ry = cos_x * ry + (-sin_x) * rz;
        rz = sin_x * temp_y + cos_x * rz;  // 原本ry的地方以temp_y取代

        // 繞y軸旋轉
        int temp_x = rx;  // 稍後rx會被蓋掉,先保存起來
        rx = cos_y * rx + sin_y * rz;
        ry = ry;
        rz = (-sin_y) * temp_x + cos_y * rz;  // 原本rx的地方以temp_x取代
  1. 印出新座標
        // 印出新座標
        printf("旋轉後: rx:%f ry:%f rz:%f\n\n", rx, ry, rz);
    }
    
    return 0;
}

程式執行結果

https://ithelp.ithome.com.tw/upload/images/20190924/20111429wP2bLYPJcA.png
首先輸入原始座標,範例:(10, 20, 30)

https://ithelp.ithome.com.tw/upload/images/20190924/20111429AW1NNcyDyA.png
輸入兩組數據,分別是:

  1. 繞x軸旋轉30度(弧度大約0.523333度)
  2. 繞y軸旋轉30度(弧度大約0.523333度)

https://ithelp.ithome.com.tw/upload/images/20190924/20111429TbvqJNOAs7.jpg
途中打叉的地方表示該地方無變化,我們可以得到小小結論:

繞著某軸旋轉,則該軸座標在當次旋轉不改變


上一篇
[11屆鐵人賽Day9] 旋轉矩陣
下一篇
[11屆鐵人賽Day11] 3D引擎製作(一)
系列文
若沒有遊戲引擎、合作夥伴...做得出遊戲嗎? 不試試看不知道吧? [使用C語言]30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言